package com.telit.firecommand.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.xiaolyuh.annotation.CacheEvict;
import com.github.xiaolyuh.annotation.Cacheable;
import com.telit.common.constant.*;
import com.telit.common.dto.DistrictDTO;
import com.telit.common.entity.DataReturn;
import com.telit.common.exception.ForestBaseException;
import com.telit.common.pojo.AliPushContentPojo;
import com.telit.common.pojo.AliPushMessagePojo;
import com.telit.common.util.AliyunPushMessageUtils;
import com.telit.common.util.JwtTokenUtils;
import com.telit.common.util.MediaUrlUtils;
import com.telit.communicate.dto.SendMessageDTO;
import com.telit.communicate.feign.RemoteCommunicateService;
import com.telit.dispose.vo.resourceManagement.DictVO;
import com.telit.firecommand.dao.CommEventDao;
import com.telit.firecommand.dao.CommFireAlarmDao;
import com.telit.firecommand.dao.CommMsgCenterLogDao;
import com.telit.firecommand.dao.DictMapper;
import com.telit.firecommand.dto.CommEventDTO;
import com.telit.firecommand.dto.CommMsgCenterLog;
import com.telit.firecommand.entity.CommEvent;
import com.telit.firecommand.entity.WebsocketPushMsgLog;
import com.telit.firecommand.service.DistrictService;
import com.telit.firecommand.service.UserInfoService;
import com.telit.firecommand.service.WebSocketPushMsgLogService;
import com.telit.upms.vo.MicroSysUserAllInfoVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.MessageFormat;
import java.util.*;
import java.util.stream.Collectors;


/**
 * @Auther amy
 * @Describe 事件信息表
 */
@Service
public class EventService extends ServiceImpl<CommEventDao, CommEvent> {

    @Autowired
    private CommEventDao commEventDao;

    @Autowired
    private UserInfoService userInfoService;

    @Autowired
    private WebSocketPushMsgLogService webSocketPushMsgLogService;

    @Autowired
    private CommMsgCenterLogDao commMsgCenterLogDao;

    @Autowired
    private DictMapper dictMapper;

    @Autowired
    private CommFireAlarmDao commFireAlarmDao;

    @Autowired
    private RemoteCommunicateService communicateFeignClient;

    @Autowired
    private DistrictService districtService;

    /**
     * 分页条件查询
     *
     * @return
     */
    @Cacheable(value = "firecommand:event:listByPage", depict = "分页条件查询")
    public IPage<CommEvent> listByPage(Integer current, Integer size, CommEventDTO commEvent) {
        IPage<CommEvent> commEventPage = new Page<>(current, size);
        return baseMapper.listByCondition(commEventPage, commEvent);
    }

    /**
     * 新增
     *
     * @return
     */
    @CacheEvict(value = {"firecommand:event:listByPage", "firecommand:event:selectCountByStatus",
            "firecommand:resoure:selectFireAndEventCountByDistrictCode",
            "firecommand:event:selectCountByResourceByDistrictCode"}, allEntries = true)
    public int add(CommEvent commEvent) {
        int count = commEventDao.insert(commEvent);
        if (count == 0) {
            throw new ForestBaseException("事件上报失败");
        }
        communicateFeignClient.sendMsg(new SendMessageDTO("web", JSONObject.toJSONString(
                DataReturn.ok(MsgIdentificationConstants.REPORT_EVENT, null))));
        return count;
    }

    public CommEventDTO detail(Long id) {
        //2022-05-18 优化 避免过度请求 -------fixed by yzx-------start
        /*CommEvent commEvent = commEventDao.selectByPrimaryKey(id);
        CommEventDTO dto = new CommEventDTO();
        BeanUtils.copyProperties(commEvent,dto);

        // 如果图片有值,处理下参数
        dto.setImgUrlList(MediaUrlUtils.handleMediaUrlToList(commEvent.getImageUrl()));
        SysUserDetailVo vo = userInfoService.getUserInfo(dto.getReceiverId());
        dto.setReceiver(vo == null?null:vo.getRealName());
        SysUserDetailVo handleVo = userInfoService.getUserInfo(dto.getHandleId());
        dto.setHandleName(handleVo == null ? null:handleVo.getRealName());
        dto.setDistrictName(commFireAlarmDao.queryAddressNameByCode(commEvent.getDistrictCode()));
        return dto;*/

        CommEvent commEvent = commEventDao.selectByPrimaryKey(id);
        CommEventDTO dto = new CommEventDTO();
        BeanUtils.copyProperties(commEvent, dto);
        final Map<Long, String> idNameMapping = userInfoService.findAndConvertUserInfoByIds(
                CollUtil.newArrayList(dto.getReceiverId(), dto.getHandleId())
        );
        // 如果图片有值,处理下参数
        dto.setImgUrlList(MediaUrlUtils.handleMediaUrlToList(commEvent.getImageUrl()));
        dto.setReceiver(ObjectUtil.defaultIfNull(idNameMapping.get(dto.getReceiverId()), StrUtil.EMPTY));
        dto.setHandleName(ObjectUtil.defaultIfNull(idNameMapping.get(dto.getHandleId()), StrUtil.EMPTY));
        DistrictDTO districtDTO = districtService.qryDistrictInfo(commEvent.getDistrictCode());
        if (districtDTO != null) {
            dto.setDistrictName(districtDTO.getName());
        }
        return dto;
        //2022-05-18 优化 避免过度请求 -------fixed by yzx-------end
    }

    /**
     * 处置事件
     *
     * @return
     */
    @Transactional
    @CacheEvict(value = {"firecommand:event:listByPage", "firecommand:event:selectCountByStatus"}, allEntries = true)
    public int handleEvent(CommEvent commEvent) throws Exception {
        int count = commEventDao.updateById(commEvent);
        if (count == 0) {
            throw new ForestBaseException("事件状态修改失败");
        }

        // 新增comm_push_msg_log
        if (webSocketPushMsgLogService.queryHasRead(1, commEvent.getId()) == 0) {
            WebsocketPushMsgLog websocketPushMsgLog = WebsocketPushMsgLog.builder().userId(JwtTokenUtils.getId())
                    .eventId(commEvent.getId())
                    .eventType(0) // 0事件 1火情
                    .build();
            webSocketPushMsgLogService.addPushMsgLog(websocketPushMsgLog);
        }

        CommEvent event = commEventDao.selectByPrimaryKey(commEvent.getId());

        // 记录推送消息,并推送
        String username = JwtTokenUtils.getRealName();

        List<DictVO> dictVOList = dictMapper.listByParentCode(DictTypeConstants.DICT_TYPE_EVENT_TYPE);
        Map<String, String> dictMap = dictVOList.stream().collect(
                Collectors.toMap(DictVO::getCode, DictVO::getName, (e1, e2) -> e1));
        String type = dictMap.get(event.getType());
        String content = MessageFormat.format(NoticeTemplateConstants.EVENT_HANDLE_CONTENT, event.getFindTime(), type,
                username);
        String title = NoticeTemplateConstants.EVENT_HANDLE_TITLE;

        CommMsgCenterLog log = new CommMsgCenterLog(content, "2", new Date(), "1", username, title,
                event.getFinderId());
        commMsgCenterLogDao.insert(log);

        List<String> userList = new ArrayList<>();
        userList.add(String.valueOf(event.getFinderId()));
        Map<String, Object> contentMap = new HashMap<>();
//        contentMap.put("msgId", log.getId());
        contentMap.put("content", content);
        AliyunPushMessageUtils.customizeAdvancedPush(
                new AliPushMessagePojo(MsgConstants.TARGET_ACCOUNT, MsgConstants.PUSH_TYPE_MESSAGE,
                        MsgConstants.DEVICE_TYPE_ANDROID, title, userList,
                        new AliPushContentPojo(NoticeTypeConstants.NOTICE_TYPE_CENTER_MSG,
                                JSON.toJSONString(contentMap))));
        return count;
    }

    /**
     * 查询未读或者用户数据信息
     *
     * @return
     */
    public List<CommEvent> noDisposeEvent(Long userId) {
        MicroSysUserAllInfoVo sysUserVo = userInfoService.getUserInfo(userId);
        List<CommEvent> resultList = null;
        if (sysUserVo != null) {
            String districtCode = sysUserVo.getAreaCode();
            resultList = commEventDao.listNoReadAndNoReceive(districtCode);
        }
        return resultList;
    }

    /**
     * 接收事件
     *
     * @return
     */
    @Transactional
    @CacheEvict(value = {"firecommand:event:listByPage", "firecommand:event:selectCountByStatus"}, allEntries = true)
    public int receiveEvent(CommEvent commEvent) throws Exception {
        int count = commEventDao.updateById(commEvent);
        if (count == 0) {
            throw new ForestBaseException("事件状态修改失败");
        }

        CommEvent event = commEventDao.selectByPrimaryKey(commEvent.getId());

        // 记录推送消息,并推送
        String username = JwtTokenUtils.getRealName();

        List<DictVO> dictVOList = dictMapper.listByParentCode(DictTypeConstants.DICT_TYPE_EVENT_TYPE);
        Map<String, String> dictMap = dictVOList.stream().collect(
                Collectors.toMap(DictVO::getCode, DictVO::getName, (e1, e2) -> e1));
        String type = dictMap.get(event.getType());
        String content = MessageFormat.format(NoticeTemplateConstants.EVENT_RECEIVE_CONTENT, event.getFindTime(), type,
                username);
        String title = NoticeTemplateConstants.EVENT_RECEIVE_TITLE;
        CommMsgCenterLog log = new CommMsgCenterLog(content, "2", new Date(), "1", username, title,
                event.getFinderId());
        commMsgCenterLogDao.insert(log);

        List<String> userList = new ArrayList<>();
        userList.add(String.valueOf(event.getFinderId()));
        Map<String, Object> contentMap = new HashMap<>();
//        contentMap.put("msgId", log.getId());
        contentMap.put("content", content);

        AliyunPushMessageUtils.customizeAdvancedPush(
                new AliPushMessagePojo(MsgConstants.TARGET_ACCOUNT, MsgConstants.PUSH_TYPE_MESSAGE,
                        MsgConstants.DEVICE_TYPE_ANDROID, title, userList,
                        new AliPushContentPojo(NoticeTypeConstants.NOTICE_TYPE_CENTER_MSG,
                                JSON.toJSONString(contentMap))));
        return count;
    }


    public List<CommEvent> queryUnReadEvent(Long userId) {
        //根据用户查询所有已读事件id
        List<Long> hasReadEventMsgIds = webSocketPushMsgLogService.queryHasReadMsg(0, userId);
        if (hasReadEventMsgIds != null && !hasReadEventMsgIds.isEmpty()) {
            List<CommEvent> list = this.noDisposeEvent(userId);
            if (list != null) {
                List<CommEvent> commEvents = list.stream().filter(e -> hasReadEventMsgIds.contains(e.getId())).collect(
                        Collectors.toList());
                return commEvents;
            }
        }
        return null;
    }

    public boolean queryHasUnReadEvent(Long userId) {
        //根据用户查询所有已读事件id
        List<Long> hasReadEventMsgIds = webSocketPushMsgLogService.queryHasReadMsg(0, userId);
        if (hasReadEventMsgIds != null && !hasReadEventMsgIds.isEmpty()) {
            List<CommEvent> list = this.noDisposeEvent(userId);
            if (list != null) {
                List<CommEvent> commEvents = list.stream().filter(e -> hasReadEventMsgIds.contains(e.getId())).collect(
                        Collectors.toList());
                return commEvents.size() > 0;
            }
        }
        return false;
    }

    /**
     * 根据状态查询事件数量
     *
     * @return
     */
    @Cacheable(value = "firecommand:event:selectCountByStatus", depict = "根据状态查询事件数量")
    public int selectCountByStatus(String status) {
        return commEventDao.selectCountByStatus(status);
    }

}
